home *** CD-ROM | disk | FTP | other *** search
- // version 1.03
-
- // sine angles use lookup table
- // vectors are long integers
- // surface now calculates normals for storage
-
- // Header file for the program 3D_2a.CPP
- // 18/12/94
-
- enum boolean {false, true};
- enum shading{none, hidden_line, lambert};
-
- #include <graphics.h>
- #include <conio.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- //#include <dos.h>
- #include <dir.h>
- #include <time.h>
- #include <iostream.h> // C++ i/o stream
- #include <fstream.h>
-
-
- float f_sin(int degree);
- float f_cos(int degree);
-
- #define ANGLE 0.01745329
- #define YES 1
- #define NO 0
- #define MK_FP(seg,offset) \
- ((void far *)(((unsigned long)(seg)<<16) | (unsigned)(offset)))
-
-
- // class for the vectors
- class vector
- {
- private:
- long x,y,z;
- public:
- friend vector operator+(vector op1, vector op2);
- friend vector operator-(vector op1, vector op2);
- friend vector operator-(vector op1, vector *op2);
-
- // multiply 2 vectors, dot-product
- friend long dotproduct(vector op1, vector op2);
- // find the normal of two vectors, or cross-product
- friend vector normal(vector op1, vector op2);
-
- // multiply vector and float, result is a vector, scaling operation
- friend vector operator*(float op1, vector op2);
- vector operator=(vector op2);
-
- vector(void);
-
- long get_x(void) {return x;};
- long get_y(void) {return y;};
- long get_z(void) {return z;};
-
- void assign(long mx, long my, long mz);
- void assign(vector op1);
- void assign(vector *op1);
- };
-
- vector::vector(void)
- {
- x = y = z = 0;
- }
-
- vector operator+(vector op1, vector op2)
- {
- vector temp;
-
- temp.x = op1.x + op2.x;
- temp.y = op1.y + op2.y;
- temp.z = op1.z + op2.z;
- return temp;
- }
-
- vector operator-(vector op1, vector op2)
- {
- vector temp;
-
- temp.x = op1.x - op2.x;
- temp.y = op1.y - op2.y;
- temp.z = op1.z - op2.z;
- return temp;
- }
-
- vector operator-(vector op1, vector *op2)
- {
- vector temp;
-
- temp.x = op1.x - op2 -> x;
- temp.y = op1.y - op2 -> y;
- temp.z = op1.z - op2 -> z;
- return temp;
- }
-
-
- long dotproduct(vector op1, vector op2)
- {
- long temp;
-
- temp = (op1.x * op2.x) + (op1.y * op2.y) + (op1.z * op2.z);
- return temp;
- }
-
- vector operator*(float op1, vector op2)
- {
- vector temp;
-
- temp.x = op1 * op2.x;
- temp.y = op1 * op2.y;
- temp.z = op1 * op2.z;
- return temp;
- }
-
- vector vector::operator=(vector op2)
- {
- x = op2.x;
- y = op2.y;
- z = op2.z;
- return *this;
- }
-
-
- vector normal(vector op1, vector op2)
- {
- vector temp;
-
- temp.x = op1.y*op2.z - op2.y*op1.z;
- temp.y = op1.z*op2.x - op2.z*op1.x;
- temp.z = op1.x*op2.y - op2.x*op1.y;
-
- return temp;
- }
-
- void vector::assign(long mx, long my, long mz)
- {
- x = mx;
- y = my;
- z = mz;
- }
-
- void vector::assign(vector op1)
- {
- x = op1.x;
- y = op1.y;
- z = op1.z;
- }
-
- void vector::assign(vector *op1)
- {
- x = op1 -> x;
- y = op1 -> y;
- z = op1 -> z;
- }
-
-
-
-
- class matrix
- {
- protected:
- int rho, theta, phi;
- float mat[3][4];
- public:
- friend vector operator*(vector op1, matrix op2);
- friend vector operator*(vector *op1, matrix op2);
- friend void multiply(vector *op1, matrix op2);
- friend void multiply(vector *op1, matrix *op2);
-
- matrix(void); // constructor
- ~matrix(void); // destructor
- void set_rho(int r) {rho += r;};
- void set_theta(int t);
- void set_phi(int p);
- int get_rho(void) {return rho;};
- int get_theta(void) {return theta;};
- int get_phi(void) {return phi;};
- void calculate(void);
- void set(float values[3][4]);
- };
-
- matrix::matrix(void)
- {
- for(register int i=0; i<3; i++)
- {
- for(register int j=0; j<4; j++)
- { // matrix format
- if (i==j) // i
- mat[i][j] = 1; // 0 1 2
- else // 0 . . .
- mat[i][j] = 0; // 1 . . .
- } // j 2 . . .
- } // 3 . . .
- rho = 1700;
- theta = 45;
- phi = 60;
- }
-
- void matrix::set_phi(int p)
- {
- phi += p;
- if (phi >= 360) phi -= 360;
- if (phi < 0) phi += 360;
- }
-
- void matrix::set_theta(int t)
- {
- theta += t;
- if (theta >= 360) theta -=360;
- if (theta < 0) theta += 360;
- }
-
- // load the matrix with the transformation data
- void matrix::set(float values[3][4])
- {
- for(register int i=0; i<3; i++)
- {
- for(register int j=0; j<4; j++)
- {
- mat[i][j] = values[i][j];
- }
- }
- }
-
- void matrix::calculate(void)
- {
- float sin_theta, cos_theta, sin_phi, cos_phi;
-
- sin_theta = f_sin(theta);
- cos_theta = f_cos(theta);
- sin_phi = f_sin(phi);
- cos_phi = f_cos(phi);
-
- mat[0][0] = -sin_theta;
- mat[0][1] = cos_theta;
- //mat[0][2] = 0;
- //mat[0][3] = 0;
- mat[1][0] = -(cos_theta * cos_phi);
- mat[1][1] = -(sin_theta * cos_phi);
- mat[1][2] = sin_phi;
- //mat[1][3] = 0;
- mat[2][0] = -(cos_theta * sin_phi);
- mat[2][1] = -(sin_theta * sin_phi);
- mat[2][2] = -cos_phi;
- mat[2][3] = rho;
- }
-
- // multiplies a vector with the matrix the result is
- // returned as a vector
- vector operator*(vector op1, matrix op2)
- {
- long tmp[3];
- long vec[4];
-
- for(register int i=0; i<3; i++) tmp[i] = 0;
-
- vec[0] = op1.get_x();
- vec[1] = op1.get_y();
- vec[2] = op1.get_z();
- vec[3] = 1.0;
-
- // multiply vector with transformation matrix
- for(i=0; i<3; i++)
- {
- for(register int j=0; j<4; j++)
- {
- tmp[i] = tmp[i] + (vec[j] * op2.mat[i][j]);
- }
- }
-
- vector result;
- result.assign(tmp[0], tmp[1], tmp[2]);
- return result;
- }
-
- vector operator*(vector *op1, matrix op2)
- {
- long tmp[3];
- long vec[4];
-
- for(register int i=0; i<3; i++) tmp[i] = 0;
-
- vec[0] = op1 -> get_x();
- vec[1] = op1 -> get_y();
- vec[2] = op1 -> get_z();
- vec[3] = 1.0;
-
- // multiply vector with transformation matrix
- for(i=0; i<3; i++)
- {
- for(register int j=0; j<4; j++)
- {
- tmp[i] = tmp[i] + (vec[j] * op2.mat[i][j]);
- }
- }
-
- vector result;
- result.assign(tmp[0], tmp[1], tmp[2]);
- return result;
- }
-
- void multiply(vector *op1, matrix op2)
- {
- long tmp[3];
- long vec[4];
-
- for(register int i=0; i<3; i++) tmp[i] = 0;
-
- vec[0] = op1 -> get_x();
- vec[1] = op1 -> get_y();
- vec[2] = op1 -> get_z();
- vec[3] = 1.0;
-
- // multiply vector with transformation matrix
- for(i=0; i<3; i++)
- {
- for(register int j=0; j<4; j++)
- {
- tmp[i] = tmp[i] + (vec[j] * op2.mat[i][j]);
- }
- }
-
- op1 -> assign(tmp[0], tmp[1], tmp[2]);
- }
-
- void multiply(vector *op1, matrix *op2)
- {
- long tmp[3];
- long vec[4];
-
- for(register int i=0; i<3; i++) tmp[i] = 0;
-
- vec[0] = op1 -> get_x();
- vec[1] = op1 -> get_y();
- vec[2] = op1 -> get_z();
- vec[3] = 1.0;
-
- // multiply vector with transformation matrix
- for(i=0; i<3; i++)
- {
- for(register int j=0; j<4; j++)
- {
- tmp[i] = tmp[i] + (vec[j] * op2 -> mat[i][j]);
- }
- }
-
- op1 -> assign(tmp[0], tmp[1], tmp[2]);
- }
-
-
-
-
- matrix::~matrix(void)
- {
- for(register int i=0; i<3; i++)
- {
- for(register int j=0; j<4; j++) mat[i][j] = 0;
- }
- }
-
-
-
- class surface
- {
- private:
- int vertices; // no. of vertices in the surface
- int *vert_list; // vertices list
- boolean visible; // is surface visible
- int shaded_visible;
- vector norm_vec; // normal of the surface
- public:
- surface(void);
- void init_vert(int no);
- void set_vert(int mat[]);
- int get_no_of_verts(void) {return vertices;};
- int get_vert(int pos) {return vert_list[pos];};
- boolean get_visible(void) {return visible;};
- int get_shading(void) {return shaded_visible;};
- void calculate_normal(vector *v_ptr);
- void calculate_visibility(vector light_source);
- void calculate_shading(vector light_source);
- ~surface(void);
- };
-
- surface::surface(void)
- {
- vertices = 0;
- visible = true;
- shaded_visible = 0;
- }
-
- void surface::init_vert(int no)
- {
- vertices = no;
- vert_list = new int[no];
- if (!vert_list)
- {
- cout << "Allocation failure\n";
- }
- }
-
- void surface::set_vert(int mat[])
- {
- for(register int i=0; i<vertices; i++)
- {
- vert_list[i] = mat[i];
- }
- }
-
- void surface::calculate_normal(vector *v_ptr)
- {
- vector vec_1, vec_2;
- int surf0, surf1, surf2;
-
- surf0 = vert_list[0];
- surf1 = vert_list[1];
- surf2 = vert_list[2];
- vec_1 = v_ptr[surf1] - v_ptr[surf0];
- vec_2 = v_ptr[surf2] - v_ptr[surf0];
- norm_vec = normal(vec_1, vec_2);
- }
-
- void surface::calculate_visibility(vector light_source)
- {
- if (dotproduct(norm_vec,light_source) > 0) visible = true;
- else visible = false;
- }
-
- void surface::calculate_shading(vector light_source)
- {
- float norm_x,x2,norm_y,y2,norm_z,z2;
- double norm_factor, light_factor;
- float intensity;
-
- norm_x = norm_vec.get_x();
- norm_y = norm_vec.get_y();
- norm_z = norm_vec.get_z();
- x2 = light_source.get_x();
- y2 = light_source.get_y();
- z2 = light_source.get_z();
-
- norm_factor = 1/sqrt(((double) ((norm_x*norm_x)+(norm_y*norm_y)+(norm_z*norm_z))));
- light_factor = 1/sqrt(((double) ((x2*x2)+(y2*y2)+(z2*z2))));
-
- norm_x *= norm_factor;
- norm_y *= norm_factor;
- norm_z *= norm_factor;
- x2 *= light_factor;
- y2 *= light_factor;
- z2 *= light_factor;
-
- //intensity = (x1*x2)+(y1*y2)+(z1*z2);
- intensity = (norm_x*x2)+(norm_y*y2)+(norm_z*z2);
-
- // find the shading intensity
- intensity *= 15; //15 shades of grey
-
- // is it visible ?
-
- if (intensity > 0)
- {
- shaded_visible = intensity;
- visible = true;
- }
- else
- {
- visible = false;
- shaded_visible = -1;
- }
- }
-
-
- surface::~surface(void)
- {
- delete vert_list;
- }
-
-
-
-
- // define global variables
-
- int no_of_surfaces;
- int no_of_vertices;
-
- const int origin_x = 319;
- const int origin_y = 240;
-
-
-
-
-